import { _decorator, bits, clamp, Collider2D, Color, Component, Contact2DType, instantiate, IPhysics2DContact, log, Node, randomRangeInt, toDegree, toRadian, Tween, tween, UIOpacity, Vec2, Vec3 } from 'cc';
import { Constant } from './Constant';
import { Util } from './Util';
import { BattleContext } from './BattleContext';
import { Weapon } from './Weapon';
import { PoolManager } from './PoolManager';
import { Surround } from './Surround';
import { Globals } from './Globals';
import { Bullet } from './Bullet';
import { Camera } from './Camera';
import { ProgressBar } from './ProgressBar';
import { Ebullet } from './Ebullet';
import { Skill } from './Skill';
const { ccclass, property } = _decorator;

@ccclass('Player')
export class Player extends Component {
    @property(Node) ndWeapon0:Node = null; // 武器节点
    @property(Node) ndShootStart:Node = null;
    @property(Node) ndReloadProgress:Node;

    speed:number = 4;   // 移动速度
    moveDirection:number = 0; // 弧度

    private _isMoving: boolean = false; // 是否移动中
    private _isUnattackable: boolean = false; // 是否无敌
    private _shootPos: Vec3 = new Vec3(); // 射击位置
    private _onEvent: Function;
    private _target: any;
    
    public get isMoving(): boolean {
        return this._isMoving;
    }
    public set isMoving(value: boolean) {
        this._isMoving = value;
        // TODO 行走动画 和 静止动画
    }

    attackDirection:number = 0; // 攻击方向
    autoDirection: Boolean = true; // 是否自动瞄准


    maxHp: number = 100;
    maxExp: number = 100;

    level:number = 1;
    hp: number = 101; // 血量
    ap: number = 10; // 攻击力
    dp: number = 5; // 防御力
    exp: number = 0;

    bulletCount: number = 5; // 子弹数量


    // 技能列表
    skills:Skill[] = [];


    static readonly Event = {
        HURT: 0,
        DEAD: 1,
        ADD_EXP: 2,
        LEVEL_UP: 3,
    }


    protected onEnable(): void {
        // 碰撞事件的接口
        const collider = this.node.getComponent(Collider2D);
        if(collider) {
            collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
            collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
        }
            
        this.hp = this.maxHp = 100;
        this.maxExp = this._getNextLevelExp(this.level);
        this.exp = 0;

        this.ndReloadProgress.active = false;

        this.skills.length = 0; // 清空技能列表
    }

    protected onDisable(): void {
        // 碰撞事件的接口
        const collider = this.node.getComponent(Collider2D);
        if(collider) {
            collider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
            collider.off(Contact2DType.END_CONTACT, this.onEndContact, this);
        }
        
        this.unscheduleAllCallbacks(); // 取消所有的回调函数
    }


    start() {
        this.isMoving = false;

        this.schedule(()=> {
            const nearestNode = this.getNearestMonster();
            if(nearestNode) {
                // TODO update radian

                this.attackDirection = Util.getRadian(this.node.worldPosition, nearestNode.worldPosition);
                this.autoDirection && this.setWeaponAngle(toDegree(this.attackDirection));
            }
        }, 0.1)
    }

    update(deltaTime: number) {
        if(this.isMoving) {
            // TODO 替换 Util.moveNode(this.node, this.moveDirection, this.speed);
            // 三角函数计算移动方向
            let x = this.node.position.x + Math.cos(this.moveDirection) * this.speed;
            let y = this.node.position.y + Math.sin(this.moveDirection) * this.speed;
            x = clamp(x, -1000, 1000);
            y = clamp(y, -1000, 1000);
            this.node.setPosition(x,y,0);
        }
    }

    private _getNextLevelExp(level:number) {
        return (level + 1) * 50;
    }

    learnSkill(sk:Skill) {
        const skill = this.skills.find(target => target.id === sk.id);
        if(skill) {
            skill.levelUp();
        } else {
            this.skills.push(sk);
        }

        this.updateSkills()
    }

    hurt(damage:number) {
        if(this._isUnattackable) {
            return;
        }
            this.hp -= damage;
            Util.showText(
                `${damage}`, 
                Color.RED.toHEX(),
                this.node.worldPosition,
                 BattleContext.ndTextParent);
            if(this.hp <= 0) {
                this.hp = 0;
                // notify die
                this._onEvent && this._onEvent.apply(this._target,[Player.Event.DEAD, 0])
            } else {
                // notify hurt
                this._onEvent && this._onEvent.apply(this._target,[Player.Event.HURT, damage])
            }
    }

    updateSkills(){
        // TODO 更新技能
    }

    addExp(exp:number) {
        this.exp += exp;
        this._onEvent && this._onEvent.apply(this._target,[Player.Event.ADD_EXP, exp]);

        if(this.exp >= this.maxExp) {
            this.exp -= this.maxExp;
            this.level++;
            this.ap = this.level * 10;
            this.maxExp = this._getNextLevelExp(this.level);
            this._onEvent && this._onEvent.apply(this._target,[Player.Event.LEVEL_UP, -1]);

        }
    }

    onPlayerEvent(onEvent: Function, target?:any) {
        this._onEvent = onEvent;
        this._target = target;
    }

    // TODO 这里的动画没有做 这里的东湖是龙骨动画，我没有龙骨动画，所以这里的动画处理没有按照教程的来，直接省略掉了
    // 停止动画
    // 行走动画
        // playWalk() {
    // const display = this.ndAni.getComponent(dragonBones.ArmatureDisplay);
    // display.armatureName = 'Walk';
    // display.playAnimation('Walk', 0)
    // }
    // 翻滚动画


    setWeaponAngle(angle: number) {
        // 枪的角度有bug
        this.ndWeapon0.angle = angle;
    }

    getShootPosition(){
        // const radius = 130;
        // const radian = toRadian(this.ndWeapon0.angle);
        // const startPos = this.ndWeapon0.worldPosition;

        // this._shootPos.x = startPos.x + Math.cos(radian) * radius;
        // this._shootPos.y = startPos.y + Math.sin(radian) * radius;

        // return this._shootPos;
        return this.ndShootStart.worldPosition;

    }

    getNearestMonster() {
        const monsters = BattleContext.ndMonsterParent.children;
        let min = bits.INT_MAX;
        let target: Node = null;
        for(let i = 0; i < monsters.length; i++) {
            const distance = Vec2.distance(monsters[i].worldPosition, this.node.worldPosition);
            if(distance < min) {
                target = monsters[i];
                min = distance;
            }
        }

        return target;
    }

    onBeginContact(self: Collider2D, other: Collider2D){
        // log(`Player collided with ${other.node.name}`);
        // 处理碰撞逻辑，例如：检测到与怪物碰撞，执行相应的逻辑
        // 例如：播放受伤动画，减少生命值等
        

        switch (other.group) {
            case Constant.ColliderGroup.MONSTER:
                // 怪物碰撞命中
                this.hurt(randomRangeInt(5,10));
                break;
            case Constant.ColliderGroup.MONSTER_WEAPON:
                // 怪物子弹命中
                if(other.tag === Constant.WeaponTag.EBULLET) {
                    const bullet = other.node.getComponent(Ebullet);
                    this.hurt(bullet.attack);
                }
                break;
            default:
                break;
        }

        
    }

    onEndContact(self: Collider2D, other: Collider2D){

    }

    // 射击子弹 连续发射
    startShootBullet() {
        const tw = tween(this.node)
        .call(()=>{
            const ndBullet = Globals.getNode(Constant.PrefabUrl.Bullet, BattleContext.ndWeapon);
            ndBullet.worldPosition = this.getShootPosition();
            const wp = ndBullet.getComponent(Bullet);
            wp.isMoving = true;
            wp.moveDirection = toRadian(this.ndWeapon0.angle); // 武器的角度
            wp.attack = 90 + this.ap; // 武器的攻击力
            wp.speed = 40;
            BattleContext.ndCamera.getComponent(Camera).shake();
        })
        .delay(0.1)

        tween(this.node).repeatForever(tw).start();
    }

    // 射击子弹 单发
    shootBullet() {
        if(this.bulletCount <= 0) {
            return;
        }

        this.bulletCount--;

        
        const ndBullet = Globals.getNode(Constant.PrefabUrl.Bullet, BattleContext.ndWeapon);
        ndBullet.worldPosition = this.getShootPosition();
        const wp = ndBullet.getComponent(Bullet);
        wp.isMoving = true;
        wp.moveDirection = toRadian(this.ndWeapon0.angle); // 武器的角度
        wp.attack = 90 + this.ap; // 武器的攻击力
        wp.speed = 40;
        BattleContext.ndCamera.getComponent(Camera).shake();

        if(this.bulletCount <= 0) {
            this.resloadBullet();
        }
    }

    resloadBullet(){
        this.ndWeapon0.active = false;
        this.ndReloadProgress.active = true;
        const bar = this.ndReloadProgress.getComponent(ProgressBar);
        bar.setProgress(0);
        const temp = new Vec3();
        tween(temp)
        .to(3, {x: 50}, {
            onUpdate: (target:Vec3, ratio:number) => {
                bar.setProgress(ratio);
            }
        })
        .call(()=> {
            this.ndReloadProgress.active = false;
            this.ndWeapon0.active = true;
            this.bulletCount = 5;
        })
        .start();
    }

    stopShootBullet() {
        Tween.stopAllByTarget(this.node); // 停止所有的动画
    }

    startEndlessDagger() {
        const tw = tween(this.node)
        .delay(0.1)
        .call(()=>{
            const ndDagger = Globals.getNode(Constant.PrefabUrl.DAGGER, BattleContext.ndWeapon);
            ndDagger.worldPosition = this.node.worldPosition;
            ndDagger.angle = toDegree(this.attackDirection) - 45; // 设置武器的角度
            const wp = ndDagger.getComponent(Weapon)
            wp.isMoving = true;
            wp.moveDirection = this.attackDirection;
            wp.speed = 12;
        })

        tween(this.node).repeatForever(tw).start();
    }


    startSurroundingSwords() {
        const ndSurround = Globals.getNode(Constant.PrefabUrl.SURROUND, BattleContext.ndWeapon);
        ndSurround.getComponent(Surround).isMoving = true;
    }

    castFireball(radian: number){
        const ndFireball = Globals.getNode(Constant.PrefabUrl.FIRE_BALL, BattleContext.ndWeapon);
        ndFireball.worldPosition = this.node.worldPosition;
        ndFireball.angle = toDegree(this.attackDirection) - 45; // 设置武器的角度
        const wp = ndFireball.getComponent(Weapon)
        wp.isMoving = true;
        wp.moveDirection = radian;
        wp.attack = 30 + this.ap; // 火球的伤害
        wp.speed = 12;

        return ndFireball;
    }

    castPowerFireballs() {
        const count = 20;
        const delta = 30;
        for(let i=0;i<count;i++) {
            this.scheduleOnce(()=> {
                const node = this.castFireball(toRadian(delta * i))
                node.angle = 90 + delta * i; // 设置武器的角度
            }, i* 0.020)
        }
    }


    // 释放火球
    startFireball() {
        const tw = tween(this.node)
        .delay(1.5)
        .call(()=>{
            // 发一个火球
            const ndFireball = Globals.getNode(Constant.PrefabUrl.FIRE_BALL, BattleContext.ndWeapon);
            ndFireball.worldPosition = this.node.worldPosition;
            ndFireball.angle = toDegree(this.attackDirection) - 45; // 设置武器的角度
            const wp = ndFireball.getComponent(Weapon)
            wp.isMoving = true;
            wp.moveDirection = this.attackDirection;
            wp.attack = 30 + this.ap;
            wp.speed = 12;


            // 发N个火球
            // const deltaAngle = 30; // 每个火球之间的角度差
            // const startDegree = toDegree(this.attackDirection) - deltaAngle; // 武器角度
            // for(let i=0;i<3;i++) {
            //     const ndFireball = Globals.getNode(Constant.PrefabUrl.FIRE_BALL, BattleContext.ndWeapon);
                
            //     ndFireball.worldPosition = this.node.worldPosition;
            //     ndFireball.angle = startDegree + deltaAngle * i; // 设置武器的角度
            //     const wp = ndFireball.getComponent(Weapon)
            //     wp.isMoving = true;
            //     wp.moveDirection = toRadian(startDegree + deltaAngle * i);
            //     wp.attack = 30;
            //     wp.speed = 12;
            // }


            // 酷炫一点
            // const deltaAngle = 10; // 每个火球之间的角度差
            // const startDegree = toDegree(this.attackDirection) - 7 * deltaAngle; // 武器角度
            // for(let i=0;i<15;i++) {
            //     const ndFireball = Globals.getNode(Constant.PrefabUrl.FIRE_BALL, BattleContext.ndWeapon);
                
            //     ndFireball.worldPosition = this.node.worldPosition;
            //     ndFireball.angle = startDegree + deltaAngle * i; // 设置武器的角度
            //     const wp = ndFireball.getComponent(Weapon)
            //     wp.isMoving = true;
            //     wp.moveDirection = toRadian(startDegree + deltaAngle * i);
            //     wp.attack = 30;
            //     wp.speed = 12;
            // }

        })

        tween(this.node).repeatForever(tw).start();
    }


    // 翻滚技能 - 没有龙骨动画所以这里省略了 因为没有动画所以我这里像是一个瞬移
    castRoll() {
        const distance = 200; // 翻滚的距离
        const endPos = Util.getPosition(this.node.position, this.moveDirection, distance); // 翻滚后的位置

        this.ndWeapon0.active = false;

        tween(this.node)
        .to(0.6, {position: endPos}, {easing: 'expoOut'})
        .call(()=>{
            this.ndWeapon0.active = true;
        })
        .start();
        
        // TODO 翻滚动画 没有龙骨动画所以这里省略了
    }

    // 无敌技能
    castUnattackable() {
        const op = this.node.getComponent(UIOpacity);
        op.opacity = 180;

        const restoreOpacity = () => {
            op.opacity = 255;
            this._isUnattackable = false;
        }

        this._isUnattackable = true;
        this.unschedule(restoreOpacity);
        this.scheduleOnce(restoreOpacity, 2); // 无敌时间2s
    }

}


